using System.Collections.Generic;
using Token = TBit.Compile.ASMCompile.Token;
using TBit.Compile;

namespace TBit.Instrcutions {
    public static class Call {
    
        public static int Compile(List<Token> tokens,VM vm,int i) {
            return ASMCompile.StructureInstruction_OPCODE_V(Opcode.CALL,tokens,vm,i);
        }
        public static Instruction Create(string a) {
            Instruction inst = new Instruction();
            inst.opcode = Opcode.CALL;
            inst.args.Add(new InstructionArgData(a));
            return inst;
        }
        /*
            函数调用示例:
            
            //定义函数
            0. DF @[func_a],4   //4表示函数的终止地址
            1.    POP #[R1]     //弹出参数，压入多少必须弹出多少，否则会导致程序无法正常运行
            2.    POP #[R2]
            3.    ADD #[R1],#[R2],#[R1]
            4.    RET #[R1] //退出函数，结果存储在RET寄存器

            6. CALL @[func_a]
            7. MOV $[10],#[R1]   //压入参数
            8. PUSH #[R1]
            9. MOV $[20],#[R1]
            10.PUSH #[R1] 
        */
        public static int Run(VM vm,Instruction inst){
            InstructionArgData arg1 = inst.args[0];
            Data data = vm.GetData(arg1.variable);
            if(data.type == DataType.Null)
            {
                vm.CallLibfunc(arg1.variable);
                return 1;
            }
            else
            {
                if(data.type != DataType.Function) throw new VMRunError($"{data.type}类型不可以函数方式调用");
                vm.MemoryPush(new Data(vm.pc + 1));//跳转回的位置
                Function func = data.function_data;
                vm.pc = func.start_address;
                return 0;
            }
        }
    }
}